﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace POSPlus.BTxmlWriter
{
    public class Node<TValue>
    {
        public String Name { get; private set; }
        public TValue Value { get; private set; }
        public Dictionary<String, TValue> Attributes { get; private set; }
        public Dictionary<String, Node<TValue>> Children { get; private set; }
        public Node<TValue> Parent { get; set; }

        /// <summary>
        /// <para>Initializes the attributes dictionary and children list of this <c>Node</c> so it
        /// is ready to receive both.</para>
        /// </summary>
        public Node()
        {
            Attributes = new Dictionary<String, TValue>();
            Children = new Dictionary<String, Node<TValue>>();
        }

        /// <summary>
        /// <para>Calls the default constructor to initialize the attributes and children and assigns the given
        /// values to Name and Value.</para>
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public Node(String name, TValue value) : this()
        {
            Name = name;
            Value = value;
        }

        /// <summary>
        /// <para>Calls the default constructor this() and assigns values to Name, Value and Attributes.</para>
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="attributes"></param>
        public Node(String name, TValue value, IDictionary<String, TValue> attributes) : this()
        {
            Name = name;
            Value = value;
            foreach(KeyValuePair<String, TValue> keyValuePair in attributes)
            {
                Attributes.Add(keyValuePair.Key, keyValuePair.Value);
            }
        }

        /// <summary>
        /// Adds an attribute to this node with the given key and value.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void AddAttribute(String key, TValue value)
        {
            Attributes.Add(key, value);
        }

        /// <summary>
        /// Adds the given node to the Children dictionary using the node's name as the key.
        /// </summary>
        /// <param name="node"></param>
        public void AddChild(Node<TValue> node)
        {
            node.Parent = this;
            Children.Add(node.Name, node);
        }

        /// <summary>
        /// Removes the attribute with the given key.
        /// </summary>
        /// <param name="key"></param>
        public void RemoveAttribute(String key)
        {
            Attributes.Remove(key);
        }

        /// <summary>
        /// Remove the child and all the grandchildren of that child from the Children dictionary.
        /// </summary>
        /// <param name="key"></param>
        public void RemoveChild(String key)
        {
            Attributes.Remove(key);
        }

        public String GetAncestory()
        {
            if (Parent == null)
                return String.Format("/{0}", Name);
            else
            {
                return String.Format("{0}/{1}", Parent.GetAncestory(), Name);
            }
        }

        public void SetInnerValue(TValue value)
        {
            Value = value;
        }

        public override string ToString()
        {
            return String.Format("{0}: {1}", Name, Value);
        }
    }
}
